/*
 * $QNXLicenseC:
 * Copyright 2007, QNX Software Systems. All Rights Reserved.
 * 
 * You must obtain a written license from and pay applicable license fees to QNX 
 * Software Systems before you may reproduce, modify or distribute this software, 
 * or any work that includes all or part of this software.   Free development 
 * licenses are available for evaluation and non-commercial purposes.  For more 
 * information visit http://licensing.qnx.com or email licensing@qnx.com.
 *  
 * This file may contain contributions from others.  Please review this entire 
 * file for other proprietary rights or license notices, as well as the QNX 
 * Development Suite License Guide at http://licensing.qnx.com/license-guide/ 
 * for other information.
 * $
 */




#ifdef __USAGE		/* cksum2.c */
%C	- display file checksums and block counts (POSIX)

%C	[-q | -v] [-9 | -12 | -o algorithm] [file]...
Options:
  -9           Use the algorithm from Draft 9   (deprecated - use -o)
  -12          Use the algorithm from Draft 12  (deprecated - use -o)
  -o algorithm Use the specified algorithm. Choices are:

                 1   Use historic 16-bit checksum algorithm.
                 2   Use historic 32-bit checksum algorithm.
                 9   Use 1003.2 draft 9 algorithm (QNX 4.0)
                 11  Use 1003.2 draft 11 algorithm
                 12  Use 1003.2 draft 12 algorithm
                 92  Use 1003.2-1992 standard algorithm (DEFAULT)
                 4.1 Use old QNX cksum algorithm (QNX 4.10-4.21)

  -q           Quiet. Do not display header (counteracts -v). (Default)
  -v           Verbose. Display a header which states the algorithm
               used and names the output columns.
Where:
  file   is the pathname of a file to be checked

Note:
  Output block counts are blocks of 1024 bytes for -o1, 512 bytes
  for -o2, and 1 byte (simple byte count) for all other algorithms.

  This version of CKSUM looks for an environment variable CKSUM,
  which defines a default option used for cksum. e.g.

  To set the default behaviour to be QNX 4.1,
  
  export CKSUM=-o4.1

  In the case where multiple options are named, there should be no
  white space separating the options. e.g. CKSUM=-vo4.1

  Command line options override the behaviour dictated by CKSUM.
#endif

#ifdef __USAGENTO 
%C	- display file checksums and block counts (POSIX)

%C	[-q | -v] [-o algorithm] [file]...
Options:
  -o algorithm Use the specified algorithm. Choices are:

                 1   Use historic 16-bit checksum algorithm.
                 2   Use historic 32-bit checksum algorithm.
                 9   Use 1003.2 draft 9 algorithm (QNX 4.0)
                 11  Use 1003.2 draft 11 algorithm
                 12  Use 1003.2 draft 12 algorithm
                 92  Use 1003.2-1992 standard algorithm (DEFAULT)
                 4.1 Use old QNX cksum algorithm (QNX 4.10-4.21)

  -q           Quiet. Do not display header (counteracts -v). (Default)
  -v           Verbose. Display a header which states the algorithm
               used and names the output columns.
Where:
  file   is the pathname of a file to be checked

Note:
  Output block counts are blocks of 1024 bytes for -o1, 512 bytes
  for -o2, and 1 byte (simple byte count) for all other algorithms.

  The QNX4.23+ CKSUM environment variable is NOT supported
  under Neutrino.
#endif

/*******************************************************************************
 *
 * NAME:		cksum
 * SYNOPSIS:	cksum [file...]
 *
 * DESCRIPTION:	The cksum utility calculates and writes to standard output a
 *				checksum (CRC) for each input file, and writes to standard
 *				output the number of bytes in each file.
 *
 * OPTIONS:		-9 use the 1003.2 draft 9 algorithm.
 *
 * CONFORMANCE:	P1003.2, Draft 11, option -9 to use algorithm from 1003.2 d 9
 *
 * AUTHOR:		Luc Bazinet. October 2, 1989	( Initial version )
 *              Eric Johnson. July 16, 1991		(1003.2 draft 11 mods)
 ******************************************************************************/

#include <lib/compat.h>
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>

#define	BUF_SIZE	((int)4096)		/* Buffer size (bytes) */

/* ---------------------------------------------------------- prototypes ---- */

unsigned long memcrc(unsigned char *pt, int n,unsigned long crc );
unsigned long strncrc(unsigned char *b,int n,unsigned long s);
unsigned long strncrcb(unsigned char *b,int n,unsigned long s);
unsigned long memcrc3 (unsigned char *b,int n,unsigned long s);
unsigned long finish_crc3 (off_t tot_len, unsigned long s);
unsigned long sum16(unsigned char *b,int n,unsigned long s);
unsigned long sum32(unsigned char *b,int n,unsigned long s);
unsigned long finish_sum32 (off_t, unsigned long);
void printstd(unsigned long crc, off_t length, char *fname);
void print1(unsigned long crc, off_t length, char *fname);
void print2(unsigned long crc, off_t length, char *fname);

int      process(int fnum,char *fname, unsigned long (*crcfn)(unsigned char *, int, unsigned long) );
int		 process_args( int argc, char **argv);

/* ---------------------------------------------------------- globals ------- */

unsigned char	buf[BUF_SIZE];
char			*prg_name;

/* table for 1003.2 draft 9 algorithm */
static	const unsigned long crctab[] = {
		0x000,	0x057,	0x0af,	0x0f8,	0x15e,	0x109,	0x1f1,	0x1a6,
		0x2bc,	0x2eb,	0x213,	0x244,	0x3e2,	0x3b5,	0x34d,	0x31a,
		0x178,	0x12f,	0x1d7,	0x180,	0x026,	0x071,	0x089,	0x0de,
		0x3c4,	0x393,	0x36b,	0x33c,	0x29a,	0x2cd,	0x235,	0x262,
		0x2f0,	0x2a7,	0x25f,	0x208,	0x3ae,	0x3f9,	0x301,	0x356,
		0x04c,	0x01b,	0x0e3,	0x0b4,	0x112,	0x145,	0x1bd,	0x1ea,
		0x388,	0x3df,	0x327,	0x370,	0x2d6,	0x281,	0x279,	0x22e,
		0x134,	0x163,	0x19b,	0x1cc,	0x06a,	0x03d,	0x0c5,	0x092,
		0x1e0,	0x1b7,	0x14f,	0x118,	0x0be,	0x0e9,	0x011,	0x046,
		0x35c,	0x30b,	0x3f3,	0x3a4,	0x202,	0x255,	0x2ad,	0x2fa,
		0x098,	0x0cf,	0x037,	0x060,	0x1c6,	0x191,	0x169,	0x13e,
		0x224,	0x273,	0x28b,	0x2dc,	0x37a,	0x32d,	0x3d5,	0x382,
		0x310,	0x347,	0x3bf,	0x3e8,	0x24e,	0x219,	0x2e1,	0x2b6,
		0x1ac,	0x1fb,	0x103,	0x154,	0x0f2,	0x0a5,	0x05d,	0x00a,
		0x268,	0x23f,	0x2c7,	0x290,	0x336,	0x361,	0x399,	0x3ce,
		0x0d4,	0x083,	0x07b,	0x02c,	0x18a,	0x1dd,	0x125,	0x172,
};

/* table from 1003.2 draft 11 algorithm */
static const unsigned long crctab2[] = { 
	0x7fffffff,
	0x77073096,	0xee0e612c,	0x990951ba,	0x076dc419,	0x706af48f,
	0xe963a535,	0x9e6495a3,	0x0edb8832,	0x79dcb8a4,	0xe0d5e91e,
	0x97d2d988,	0x09b64c2b,	0x7eb17cbd,	0xe7b82d07,	0x90bf1d91,
	0x1db71064,	0x6ab020f2,	0xf3b97148,	0x84be41de,	0x1adad47d,
	0x6ddde4eb,	0xf4d4b551,	0x83d385c7,	0x136c9856,	0x646ba8c0,
	0xfd62f97a,	0x8a65c9ec,	0x14015c4f,	0x63066cd9,	0xfa0f3d63,
	0x8d080df5,	0x3b6e20c8,	0x4c69105e,	0xd56041e4,	0xa2677172,
	0x3c03e4d1,	0x4b04d447,	0xd20d85fd,	0xa50ab56b,	0x35b5a8fa,
	0x42b2986c,	0xdbbbc9d6,	0xacbcf940,	0x32d86ce3,	0x45df5c75,
	0xdcd60dcf,	0xabd13d59,	0x26d930ac,	0x51de003a,	0xc8d75180,
	0xbfd06116,	0x21b4f4b5,	0x56b3c423,	0xcfba9599,	0xb8bda50f,
	0x2802b89e,	0x5f058808,	0xc60cd9b2,	0xb10be924,	0x2f6f7c87,
	0x58684c11,	0xc1611dab,	0xb6662d3d,	0x76dc4190,	0x01db7106,
	0x98d220bc,	0xefd5102a,	0x71b18589,	0x06b6b51f,	0x9fbfe4a5,
	0xe8b8d433,	0x7807c9a2,	0x0f00f934,	0x9609a88e,	0xe10e9818,
	0x7f6a0dbb,	0x086d3d2d,	0x91646c97,	0xe6635c01,	0x6b6b51f4,
	0x1c6c6162,	0x856530d8,	0xf262004e,	0x6c0695ed,	0x1b01a57b,
	0x8208f4c1,	0xf50fc457,	0x65b0d9c6,	0x12b7e950,	0x8bbeb8ea,
	0xfcb9887c,	0x62dd1ddf,	0x15da2d49,	0x8cd37cf3,	0xfbd44c65,
	0x4db26158,	0x3ab551ce,	0xa3bc0074,	0xd4bb30e2,	0x4adfa541,
	0x3dd895d7,	0xa4d1c46d,	0xd3d6f4fb,	0x4369e96a,	0x346ed9fc,
	0xad678846,	0xda60b8d0,	0x44042d73,	0x33031de5,	0xaa0a4c5f,
	0xdd0d7cc9,	0x5005713c,	0x270241aa,	0xbe0b1010,	0xc90c2086,
	0x5768b525,	0x206f85b3,	0xb966d409,	0xce61e49f,	0x5edef90e,
	0x29d9c998,	0xb0d09822,	0xc7d7a8b4,	0x59b33d17,	0x2eb40d81,
	0xb7bd5c3b,	0xc0ba6cad,	0xedb88320,	0x9abfb3b6,	0x03b6e20c,
	0x74b1d29a,	0xead54739,	0x9dd277af,	0x04db2615,	0x73dc1683,
	0xe3630b12,	0x94643b84,	0x0d6d6a3e,	0x7a6a5aa8,	0xe40ecf0b,
	0x9309ff9d,	0x0a00ae27,	0x7d079eb1,	0xf00f9344,	0x8708a3d2,
	0x1e01f268,	0x6906c2fe,	0xf762575d,	0x806567cb,	0x196c3671,
	0x6e6b06e7,	0xfed41b76,	0x89d32be0,	0x10da7a5a,	0x67dd4acc,
	0xf9b9df6f,	0x8ebeeff9,	0x17b7be43,	0x60b08ed5,	0xd6d6a3e3,
	0xa1d1937e,	0x38d8c2c4,	0x4fdff252,	0xd1bb67f1,	0xa6bc5767,
	0x3fb506dd,	0x48b2364b,	0xd80d2bda,	0xaf0a1b4c,	0x36034af6,
	0x41047a60,	0xdf60efc3,	0xa867df55,	0x316e8eef,	0x4669be79,
	0xcb61b38c,	0xbc66831a,	0x256fd2a0,	0x5268e236,	0xcc0c7795,
	0xbb0b4703,	0x220216b9,	0x5505262f,	0xc5ba3bbe,	0xb2bd0b28,
	0x2bb45a92,	0x5cb36a04,	0xc2d7ffa7,	0xb5d0cf31,	0x2cd99e8b,
	0x5bdeae1d,	0x9b64c2b0,	0xec63f226,	0x756aa39c,	0x026d930a,
	0x9c0906a9,	0xeb0e363f,	0x72076785,	0x05005713,	0x95bf4a82,
	0xe2b87a14,	0x7bb12bae,	0x0cb61b38,	0x92d28e9b,	0xe5d5be0d,
	0x7cdcefb7,	0x0bdbdf21,	0x86d3d2d4,	0xf1d4e242,	0x68ddb3f8,
	0x1fda836e,	0x81be16cd,	0xf6b9265b,	0x6fb077e1,	0x18b74777,
	0x88085ae6,	0xff0f6a70,	0x66063bca,	0x11010b5c,	0x8f659eff,
	0xf862ae69,	0x616bffd3,	0x166ccf45,	0xa00ae278,	0xd70dd2ee,
	0x4e048354,	0x3903b3c2,	0xa7672661,	0xd06016f7,	0x4969474d,
	0x3e6e77db,	0xaed16a4a,	0xd9d65adc,	0x40df0b66,	0x37d83bf0,
	0xa9bcae53,	0xdebb9ec5,	0x47b2cf7f,	0x30b5ffe9,	0xbdbdf21c,
	0xcabac28a,	0x53b39330,	0x24b4a3a6,	0xbad03605,	0xcdd70693,
	0x54de5729,	0x23d967bf,	0xb3667a2e,	0xc4614ab8,	0x5d681b02,
	0x2a6f2b94,	0xb40bbe37,	0xc30c8ea1,	0x5a05df1b,	0x2d02ef8d
};

/* corrected table from 1003.2 draft 11 algorithm */
static const unsigned long crctab2b[] = { 
	0x7fffffff,
	0x77073096,	0xee0e612c,	0x990951ba,	0x076dc419,	0x706af48f,
	0xe963a535,	0x9e6495a3,	0x0edb8832,	0x79dcb8a4,	0xe0d5e91e,
	0x97d2d988,	0x09b64c2b,	0x7eb17cbd,	0xe7b82d07,	0x90bf1d91,
	0x1db71064,	0x6ab020f2,	0xf3b97148,	0x84be41de,	0x1adad47d,
	0x6ddde4eb,	0xf4d4b551,	0x83d385c7,	0x136c9856,	0x646ba8c0,
	0xfd62f97a,	0x8a65c9ec,	0x14015c4f,	0x63066cd9,	0xfa0f3d63,
	0x8d080df5,	0x3b6e20c8,	0x4c69105e,	0xd56041e4,	0xa2677172,
	0x3c03e4d1,	0x4b04d447,	0xd20d85fd,	0xa50ab56b,	0x35b5a8fa,
	0x42b2986c,	0xdbbbc9d6,	0xacbcf940,	0x32d86ce3,	0x45df5c75,
	0xdcd60dcf,	0xabd13d59,	0x26d930ac,	0x51de003a,	0xc8d75180,
	0xbfd06116,	0x21b4f4b5,	0x56b3c423,	0xcfba9599,	0xb8bda50f,
	0x2802b89e,	0x5f058808,	0xc60cd9b2,	0xb10be924,	0x2f6f7c87,
	0x58684c11,	0xc1611dab,	0xb6662d3d,	0x76dc4190,	0x01db7106,
	0x98d220bc,	0xefd5102a,	0x71b18589,	0x06b6b51f,	0x9fbfe4a5,
	0xe8b8d433,	0x7807c9a2,	0x0f00f934,	0x9609a88e,	0xe10e9818,
	0x7f6a0dbb,	0x086d3d2d,	0x91646c97,	0xe6635c01,	0x6b6b51f4,
	0x1c6c6162,	0x856530d8,	0xf262004e,	0x6c0695ed,	0x1b01a57b,
	0x8208f4c1,	0xf50fc457,	0x65b0d9c6,	0x12b7e950,	0x8bbeb8ea,
	0xfcb9887c,	0x62dd1ddf,	0x15da2d49,	0x8cd37cf3,	0xfbd44c65,
	0x4db26158,	0x3ab551ce,	0xa3bc0074,	0xd4bb30e2,	0x4adfa541,
	0x3dd895d7,	0xa4d1c46d,	0xd3d6f4fb,	0x4369e96a,	0x346ed9fc,
	0xad678846,	0xda60b8d0,	0x44042d73,	0x33031de5,	0xaa0a4c5f,
	0xdd0d7cc9,	0x5005713c,	0x270241aa,	0xbe0b1010,	0xc90c2086,
	0x5768b525,	0x206f85b3,	0xb966d409,	0xce61e49f,	0x5edef90e,
	0x29d9c998,	0xb0d09822,	0xc7d7a8b4,	0x59b33d17,	0x2eb40d81,
	0xb7bd5c3b,	0xc0ba6cad,	0xedb88320,	0x9abfb3b6,	0x03b6e20c,
	0x74b1d29a,	0xead54739,	0x9dd277af,	0x04db2615,	0x73dc1683,
	0xe3630b12,	0x94643b84,	0x0d6d6a3e,	0x7a6a5aa8,	0xe40ecf0b,
	0x9309ff9d,	0x0a00ae27,	0x7d079eb1,	0xf00f9344,	0x8708a3d2,
	0x1e01f268,	0x6906c2fe,	0xf762575d,	0x806567cb,	0x196c3671,
	0x6e6b06e7,	0xfed41b76,	0x89d32be0,	0x10da7a5a,	0x67dd4acc,
	0xf9b9df6f,	0x8ebeeff9,	0x17b7be43,	0x60b08ed5,	0xd6d6a3e8,
	0xa1d1937e,	0x38d8c2c4,	0x4fdff252,	0xd1bb67f1,	0xa6bc5767,
	0x3fb506dd,	0x48b2364b,	0xd80d2bda,	0xaf0a1b4c,	0x36034af6,
	0x41047a60,	0xdf60efc3,	0xa867df55,	0x316e8eef,	0x4669be79,
	0xcb61b38c,	0xbc66831a,	0x256fd2a0,	0x5268e236,	0xcc0c7795,
	0xbb0b4703,	0x220216b9,	0x5505262f,	0xc5ba3bbe,	0xb2bd0b28,
	0x2bb45a92,	0x5cb36a04,	0xc2d7ffa7,	0xb5d0cf31,	0x2cd99e8b,
	0x5bdeae1d,	0x9b64c2b0,	0xec63f226,	0x756aa39c,	0x026d930a,
	0x9c0906a9,	0xeb0e363f,	0x72076785,	0x05005713,	0x95bf4a82,
	0xe2b87a14,	0x7bb12bae,	0x0cb61b38,	0x92d28e9b,	0xe5d5be0d,
	0x7cdcefb7,	0x0bdbdf21,	0x86d3d2d4,	0xf1d4e242,	0x68ddb3f8,
	0x1fda836e,	0x81be16cd,	0xf6b9265b,	0x6fb077e1,	0x18b74777,
	0x88085ae6,	0xff0f6a70,	0x66063bca,	0x11010b5c,	0x8f659eff,
	0xf862ae69,	0x616bffd3,	0x166ccf45,	0xa00ae278,	0xd70dd2ee,
	0x4e048354,	0x3903b3c2,	0xa7672661,	0xd06016f7,	0x4969474d,
	0x3e6e77db,	0xaed16a4a,	0xd9d65adc,	0x40df0b66,	0x37d83bf0,
	0xa9bcae53,	0xdebb9ec5,	0x47b2cf7f,	0x30b5ffe9,	0xbdbdf21c,
	0xcabac28a,	0x53b39330,	0x24b4a3a6,	0xbad03605,	0xcdd70693,
	0x54de5729,	0x23d967bf,	0xb3667a2e,	0xc4614ab8,	0x5d681b02,
	0x2a6f2b94,	0xb40bbe37,	0xc30c8ea1,	0x5a05df1b,	0x2d02ef8d
};

/* table from 1003.2 draft 12 algorithm */
static const unsigned long crctab3[] = { 
	0x0,
	0x77073096,	0xee0e612c,	0x990951ba,	0x076dc419,	0x706af48f,
	0xe963a535,	0x9e6495a3,	0x0edb8832,	0x79dcb8a4,	0xe0d5e91e,
	0x97d2d988,	0x09b64c2b,	0x7eb17cbd,	0xe7b82d07,	0x90bf1d91,
	0x1db71064,	0x6ab020f2,	0xf3b97148,	0x84be41de,	0x1adad47d,
	0x6ddde4eb,	0xf4d4b551,	0x83d385c7,	0x136c9856,	0x646ba8c0,
	0xfd62f97a,	0x8a65c9ec,	0x14015c4f,	0x63066cd9,	0xfa0f3d63,
	0x8d080df5,	0x3b6e20c8,	0x4c69105e,	0xd56041e4,	0xa2677172,
	0x3c03e4d1,	0x4b04d447,	0xd20d85fd,	0xa50ab56b,	0x35b5a8fa,
	0x42b2986c,	0xdbbbc9d6,	0xacbcf940,	0x32d86ce3,	0x45df5c75,
	0xdcd60dcf,	0xabd13d59,	0x26d930ac,	0x51de003a,	0xc8d75180,
	0xbfd06116,	0x21b4f4b5,	0x56b3c423,	0xcfba9599,	0xb8bda50f,
	0x2802b89e,	0x5f058808,	0xc60cd9b2,	0xb10be924,	0x2f6f7c87,
	0x58684c11,	0xc1611dab,	0xb6662d3d,	0x76dc4190,	0x01db7106,
	0x98d220bc,	0xefd5102a,	0x71b18589,	0x06b6b51f,	0x9fbfe4a5,
	0xe8b8d433,	0x7807c9a2,	0x0f00f934,	0x9609a88e,	0xe10e9818,
	0x7f6a0dbb,	0x086d3d2d,	0x91646c97,	0xe6635c01,	0x6b6b51f4,
	0x1c6c6162,	0x856530d8,	0xf262004e,	0x6c0695ed,	0x1b01a57b,
	0x8208f4c1,	0xf50fc457,	0x65b0d9c6,	0x12b7e950,	0x8bbeb8ea,
	0xfcb9887c,	0x62dd1ddf,	0x15da2d49,	0x8cd37cf3,	0xfbd44c65,
	0x4db26158,	0x3ab551ce,	0xa3bc0074,	0xd4bb30e2,	0x4adfa541,
	0x3dd895d7,	0xa4d1c46d,	0xd3d6f4fb,	0x4369e96a,	0x346ed9fc,
	0xad678846,	0xda60b8d0,	0x44042d73,	0x33031de5,	0xaa0a4c5f,
	0xdd0d7cc9,	0x5005713c,	0x270241aa,	0xbe0b1010,	0xc90c2086,
	0x5768b525,	0x206f85b3,	0xb966d409,	0xce61e49f,	0x5edef90e,
	0x29d9c998,	0xb0d09822,	0xc7d7a8b4,	0x59b33d17,	0x2eb40d81,
	0xb7bd5c3b,	0xc0ba6cad,	0xedb88320,	0x9abfb3b6,	0x03b6e20c,
	0x74b1d29a,	0xead54739,	0x9dd277af,	0x04db2615,	0x73dc1683,
	0xe3630b12,	0x94643b84,	0x0d6d6a3e,	0x7a6a5aa8,	0xe40ecf0b,
	0x9309ff9d,	0x0a00ae27,	0x7d079eb1,	0xf00f9344,	0x8708a3d2,
	0x1e01f268,	0x6906c2fe,	0xf762575d,	0x806567cb,	0x196c3671,
	0x6e6b06e7,	0xfed41b76,	0x89d32be0,	0x10da7a5a,	0x67dd4acc,
	0xf9b9df6f,	0x8ebeeff9,	0x17b7be43,	0x60b08ed5,	0xd6d6a3e3,
	0xa1d1937e,	0x38d8c2c4,	0x4fdff252,	0xd1bb67f1,	0xa6bc5767,
	0x3fb506dd,	0x48b2364b,	0xd80d2bda,	0xaf0a1b4c,	0x36034af6,
	0x41047a60,	0xdf60efc3,	0xa867df55,	0x316e8eef,	0x4669be79,
	0xcb61b38c,	0xbc66831a,	0x256fd2a0,	0x5268e236,	0xcc0c7795,
	0xbb0b4703,	0x220216b9,	0x5505262f,	0xc5ba3bbe,	0xb2bd0b28,
	0x2bb45a92,	0x5cb36a04,	0xc2d7ffa7,	0xb5d0cf31,	0x2cd99e8b,
	0x5bdeae1d,	0x9b64c2b0,	0xec63f226,	0x756aa39c,	0x026d930a,
	0x9c0906a9,	0xeb0e363f,	0x72076785,	0x05005713,	0x95bf4a82,
	0xe2b87a14,	0x7bb12bae,	0x0cb61b38,	0x92d28e9b,	0xe5d5be0d,
	0x7cdcefb7,	0x0bdbdf21,	0x86d3d2d4,	0xf1d4e242,	0x68ddb3f8,
	0x1fda836e,	0x81be16cd,	0xf6b9265b,	0x6fb077e1,	0x18b74777,
	0x88085ae6,	0xff0f6a70,	0x66063bca,	0x11010b5c,	0x8f659eff,
	0xf862ae69,	0x616bffd3,	0x166ccf45,	0xa00ae278,	0xd70dd2ee,
	0x4e048354,	0x3903b3c2,	0xa7672661,	0xd06016f7,	0x4969474d,
	0x3e6e77db,	0xaed16a4a,	0xd9d65adc,	0x40df0b66,	0x37d83bf0,
	0xa9bcae53,	0xdebb9ec5,	0x47b2cf7f,	0x30b5ffe9,	0xbdbdf21c,
	0xcabac28a,	0x53b39330,	0x24b4a3a6,	0xbad03605,	0xcdd70693,
	0x54de5729,	0x23d967bf,	0xb3667a2e,	0xc4614ab8,	0x5d681b02,
	0x2a6f2b94,	0xb40bbe37,	0xc30c8ea1,	0x5a05df1b,	0x2d02ef8d
};

/* table from 1003.2-1992 (final standard) algorithm */
static const unsigned long crctab4[] = {
	0x0,
	0x04c11db7, 0x09823b6e, 0x0d4326d9, 0x130476dc, 0x17c56b6b,
	0x1a864db2, 0x1e475005, 0x2608edb8, 0x22c9f00f, 0x2f8ad6d6,
	0x2b4bcb61, 0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd,
	0x4c11db70, 0x48d0c6c7, 0x4593e01e, 0x4152fda9, 0x5f15adac,
	0x5bd4b01b, 0x569796c2, 0x52568b75, 0x6a1936c8, 0x6ed82b7f,
	0x639b0da6, 0x675a1011, 0x791d4014, 0x7ddc5da3, 0x709f7b7a,
	0x745e66cd, 0x9823b6e0, 0x9ce2ab57, 0x91a18d8e, 0x95609039,
	0x8b27c03c, 0x8fe6dd8b, 0x82a5fb52, 0x8664e6e5, 0xbe2b5b58,
	0xbaea46ef, 0xb7a96036, 0xb3687d81, 0xad2f2d84, 0xa9ee3033,
	0xa4ad16ea, 0xa06c0b5d, 0xd4326d90, 0xd0f37027, 0xddb056fe,
	0xd9714b49, 0xc7361b4c, 0xc3f706fb, 0xceb42022, 0xca753d95,
	0xf23a8028, 0xf6fb9d9f, 0xfbb8bb46, 0xff79a6f1, 0xe13ef6f4,
	0xe5ffeb43, 0xe8bccd9a, 0xec7dd02d, 0x34867077, 0x30476dc0,
	0x3d044b19, 0x39c556ae, 0x278206ab, 0x23431b1c, 0x2e003dc5,
	0x2ac12072, 0x128e9dcf, 0x164f8078, 0x1b0ca6a1, 0x1fcdbb16,
	0x018aeb13, 0x054bf6a4, 0x0808d07d, 0x0cc9cdca, 0x7897ab07,
	0x7c56b6b0, 0x71159069, 0x75d48dde, 0x6b93dddb, 0x6f52c06c,
	0x6211e6b5, 0x66d0fb02, 0x5e9f46bf, 0x5a5e5b08, 0x571d7dd1,
	0x53dc6066, 0x4d9b3063, 0x495a2dd4, 0x44190b0d, 0x40d816ba,
	0xaca5c697, 0xa864db20, 0xa527fdf9, 0xa1e6e04e, 0xbfa1b04b,
	0xbb60adfc, 0xb6238b25, 0xb2e29692, 0x8aad2b2f, 0x8e6c3698,
	0x832f1041, 0x87ee0df6, 0x99a95df3, 0x9d684044, 0x902b669d,
	0x94ea7b2a, 0xe0b41de7, 0xe4750050, 0xe9362689, 0xedf73b3e,
	0xf3b06b3b, 0xf771768c, 0xfa325055, 0xfef34de2, 0xc6bcf05f,
	0xc27dede8, 0xcf3ecb31, 0xcbffd686, 0xd5b88683, 0xd1799b34,
	0xdc3abded, 0xd8fba05a, 0x690ce0ee, 0x6dcdfd59, 0x608edb80,
	0x644fc637, 0x7a089632, 0x7ec98b85, 0x738aad5c, 0x774bb0eb,
	0x4f040d56, 0x4bc510e1, 0x46863638, 0x42472b8f, 0x5c007b8a,
	0x58c1663d, 0x558240e4, 0x51435d53, 0x251d3b9e, 0x21dc2629,
	0x2c9f00f0, 0x285e1d47, 0x36194d42, 0x32d850f5, 0x3f9b762c,
	0x3b5a6b9b, 0x0315d626, 0x07d4cb91, 0x0a97ed48, 0x0e56f0ff,
	0x1011a0fa, 0x14d0bd4d, 0x19939b94, 0x1d528623, 0xf12f560e,
	0xf5ee4bb9, 0xf8ad6d60, 0xfc6c70d7, 0xe22b20d2, 0xe6ea3d65,
	0xeba91bbc, 0xef68060b, 0xd727bbb6, 0xd3e6a601, 0xdea580d8,
	0xda649d6f, 0xc423cd6a, 0xc0e2d0dd, 0xcda1f604, 0xc960ebb3,
	0xbd3e8d7e, 0xb9ff90c9, 0xb4bcb610, 0xb07daba7, 0xae3afba2,
	0xaafbe615, 0xa7b8c0cc, 0xa379dd7b, 0x9b3660c6, 0x9ff77d71,
	0x92b45ba8, 0x9675461f, 0x8832161a, 0x8cf30bad, 0x81b02d74,
	0x857130c3, 0x5d8a9099, 0x594b8d2e, 0x5408abf7, 0x50c9b640,
	0x4e8ee645, 0x4a4ffbf2, 0x470cdd2b, 0x43cdc09c, 0x7b827d21,
	0x7f436096, 0x7200464f, 0x76c15bf8, 0x68860bfd, 0x6c47164a,
	0x61043093, 0x65c52d24, 0x119b4be9, 0x155a565e, 0x18197087,
	0x1cd86d30, 0x029f3d35, 0x065e2082, 0x0b1d065b, 0x0fdc1bec,
	0x3793a651, 0x3352bbe6, 0x3e119d3f, 0x3ad08088, 0x2497d08d,
	0x2056cd3a, 0x2d15ebe3, 0x29d4f654, 0xc5a92679, 0xc1683bce,
	0xcc2b1d17, 0xc8ea00a0, 0xd6ad50a5, 0xd26c4d12, 0xdf2f6bcb,
	0xdbee767c, 0xe3a1cbc1, 0xe760d676, 0xea23f0af, 0xeee2ed18,
	0xf0a5bd1d, 0xf464a0aa, 0xf9278673, 0xfde69bc4, 0x89b8fd09,
	0x8d79e0be, 0x803ac667, 0x84fbdbd0, 0x9abc8bd5, 0x9e7d9662,
	0x933eb0bb, 0x97ffad0c, 0xafb010b1, 0xab710d06, 0xa6322bdf,
	0xa2f33668, 0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4
};

static const unsigned long *crctable=crctab4;
unsigned long (*crcfn)(unsigned char *, int, unsigned long) = memcrc3;
unsigned long (*crcendfn)(off_t, unsigned long) = finish_crc3;
void		  (*crcprintfn)(unsigned long, off_t, char *) = printstd;

int verbose=0;


  /* -------------------------------------------------------------- main  ----- */

int main(int argc, char **argv)
{
	int fd, i, status=EXIT_SUCCESS;
#ifdef SUPPORT_OLD_OPTIONS
    char *defaults[2];

	defaults[0]=argv[0];

	if (NULL!=(defaults[1]=getenv("CKSUM"))) status|=process_args(2,defaults);
#endif

#ifndef __QNXNTO__
	optind=0;
#else
	optind=1;
#endif

	status |= process_args(argc,argv);

	if (status!=EXIT_SUCCESS) exit(status);
	
	prg_name = argv[0];		/* Setup program name, in case of error.	*/

	if (verbose) {
		if (crcfn==strncrc)
			fprintf(stdout,"QNX 'cksum -o 4.1' (QNX 4.10-4.21)\n");
		else if (crcfn==sum16)
			fprintf(stdout,"QNX 'cksum -o 1' (historic 16-bit checksum)\n");
		else if (crcfn==sum32)
			fprintf(stdout,"QNX 'cksum -o 2' (historic 32-bit crc)\n");
		else if (crcfn==memcrc)
			fprintf(stdout,"QNX 'cksum -o 9' (1003.2 Draft 9)\n");
		else if (crcfn==strncrcb)
			fprintf(stdout,"QNX 'cksum -o 11' (1003.2 Draft 11)\n");
		else if (crcfn==memcrc3) {
			if (crctab==crctab3)
				fprintf(stdout,"QNX 'cksum -12' (1003.2 Draft 12)\n");
   			else 
				fprintf(stdout,"QNX 'cksum'     (1003.2-1992 Standard)\n");
		}

		if (crcprintfn==print1 || crcprintfn==print2) {
			fprintf(stdout,"%s %s %s\n","Checksum","Blocks","Filename");  
		} else {
			fprintf(stdout,"%-10s %10s %s\n","Checksum","Bytes","Filename");  
		}

		fprintf(stdout,"------------------------------------------\n");
		fflush(stdout);
	}

	if (argc==optind) {
		MAKE_BINARY_FD( STDIN_FILENO );
		(void) process(STDIN_FILENO, "STDIN", crcfn);
	}
	for ( i=optind;i<argc;i++ ) {
		if (!strcmp(argv[i],"-")) {
			MAKE_BINARY_FD( STDIN_FILENO );
			(void) process(STDIN_FILENO, "STDIN", crcfn);
		} else {
			if ( (fd = open(argv[i], O_RDONLY | O_BINARY)) != -1 )	{
				(void) process(fd, argv[i], crcfn);
				close(fd);
			} else {
				perror( argv[i] );
				status=EXIT_FAILURE;
			}
		}
	}
	return (status);
}
#ifdef SUPPORT_OLD_OPTIONS
#define OPTIONS "**129qvo:"
#else
#define OPTIONS "qvo:"
#endif

int process_args( int argc, char **argv) 
{
	int c, draft12=0, status=EXIT_SUCCESS;

	while ((c=getopt(argc,argv,OPTIONS))!=-1) {
		switch(c) {
#ifdef SUPPORT_OLD_OPTIONS
			/* -12 (in sequence) means use draft 12 */
			case '1': draft12=1; break;

			case '2': if (draft12) {
						crcfn = memcrc3;
						crctable=crctab3;
						draft12=0;
						fprintf(stderr,"cksum: Warning... -12 (1003.2 draft 12 compatibility) is deprecated.\n");
					  } else {
						fprintf(stderr,"cksum: unknown option -2\n");
						draft12=0;
						status = EXIT_FAILURE;
					  }
	 				  break;

			case '9': 
				if (draft12) {
					fprintf(stderr,"cksum: unknown option -1\n");
					draft12=0;
					status = EXIT_FAILURE;
				}

				fprintf(stderr,"cksum: Warning... -9 (1003.2 draft 9 compatibility) is deprecated.\n");
				crcfn = memcrc;
				break;
#endif

			case 'o':
				if (draft12) {
					fprintf(stderr,"cksum: unknown option -1\n");
					draft12=0;
					status = EXIT_FAILURE;
				}
				
				if (!strcmp(optarg,"1")) {
					crcfn=sum16;
					crcendfn=NULL;
					crctable=NULL;
					crcprintfn=print1;
				} else if (!strcmp(optarg,"2")) {
					crcfn=sum32;
					crcendfn=finish_sum32;
					crctable=NULL;
					crcprintfn=print2;
				} else if (!strcmp(optarg,"9")) {
					crcfn=memcrc;
					crcendfn=NULL;
					crctable=crctab;
					crcprintfn=printstd;
				} else if (!strcmp(optarg,"11")) {
					crcfn=strncrcb;
					crcendfn=NULL;
					crctable=crctab2b;
					crcprintfn=printstd;
				} else if (!strcmp(optarg,"12")) {				
					crcfn=memcrc3;
					crcendfn=finish_crc3;
					crctable=crctab3;
					crcprintfn=printstd;
				} else if (!strcmp(optarg,"92")) {
					crcfn=memcrc3;
					crcendfn=finish_crc3;
					crctable=crctab4;
					crcprintfn=printstd;
				} else if (!strcmp(optarg,"4.1")) {
					crcfn = strncrc;
					crcendfn=NULL;
					crctable = crctab2;
					crcprintfn=printstd;
				} else {
					fprintf(stderr,"cksum: '-o %s' is not a known algorithm.\n",optarg);
					status=EXIT_FAILURE;
				}
				break;

			case 'v':
				if (draft12) {
					fprintf(stderr,"cksum: unknown option -1\n");
					draft12=0;
					status = EXIT_FAILURE;
				}
				verbose++;
				break;

			case 'q':
				if (draft12) {
					fprintf(stderr,"cksum: unknown option -1\n");
					draft12=0;
					status = EXIT_FAILURE;
				}
				verbose=0;
				break;

			default: 
				if (draft12) {
					fprintf(stderr,"cksum: unknown option -1\n");
					draft12=0;
				}
				status = EXIT_FAILURE;
                break;
		}
	}
	return status;
}

ssize_t do_read(int fildes, void *buf, size_t nbyte) 
{
	void *writeptr;
	size_t bytes_read;
	ssize_t rc;

	writeptr=buf;
	bytes_read=0;
	rc=1;

	while ((bytes_read<nbyte)&&rc!=0) {
		rc=read(fildes, ((char*)buf)+bytes_read, nbyte-bytes_read);
		if (rc==-1) return -1;
		bytes_read+=rc;
	}		

	return bytes_read;
}

/* -------------------------------------------------------------- process --- */
int process(int fnum,char *fname, unsigned long (*crcfn)(unsigned char *, int, unsigned long) )
{
		unsigned long	crc;
		int				len;
		off_t			tot_len;

		/*
		 *	CRC until EOF.
		 */
		crc	= 0l;
		tot_len = 0;
		while ( (len=do_read( fnum, (char *)buf, BUF_SIZE)) > 0 ) {
			crc = (*crcfn)( buf, len, crc );
			tot_len += len;
		}

		if ( len < 0 ) {
			perror(prg_name);
			return EXIT_FAILURE;
		}
		if (crcendfn!=NULL) {
			crc = (*crcendfn)(tot_len, crc);
		}

		(*crcprintfn)(crc,tot_len,fname);
		return EXIT_SUCCESS;
}

void printstd(unsigned long crc, off_t length, char *fname)
{
#if _FILE_OFFSET_BITS - 0 == 64
	(void) printf( "%10lu %10lld %s\n", crc, length, fname );
#else
	(void) printf( "%10lu %10d %s\n", crc, length, fname );
#endif
}
void print1(unsigned long crc, off_t length, char *fname)
{
#if _FILE_OFFSET_BITS - 0 == 64
	(void) printf( "%lu %lld %s\n", crc, (length+1023)/1024, fname );
#else
	(void) printf( "%lu %d %s\n", crc, (length+1023)/1024, fname );
#endif
}
void print2(unsigned long crc, off_t length, char *fname)
{
#if _FILE_OFFSET_BITS - 0 == 64
	(void) printf( "%lu %lld %s\n", crc, (length+511)/512, fname );
#else
	(void) printf( "%lu %d %s\n", crc, (length+511)/512, fname );
#endif
}

/* -------------------------------------------------------------- memcrc ---- */
/* ----------------------------------------------- draft 9 crc algorithm ---- */
unsigned long memcrc(unsigned char *pt, int n,unsigned long crc )
{
	unsigned char	*end;
	for (end=pt+n;pt<end;crc=(crc<<7)^crctab[(crc^*pt++)&0x7f]) ;
	return crc;
}

/* -------------------------------------------------------------- strncrc --- */
/* ---------------------------------------------- QNX 4.10-4.21 algorithm --- */
unsigned long strncrc(unsigned char *b,int n,unsigned long s)
{
	int	i,aux;

	aux=0;
	while (n-- > 0) {
		/* compute the index to the crc table */
		i=(s>>24)^((unsigned int)(*b++));

		if (i==0) {
			/* replace an intermediate zero with the next value from the sequence */
			i=aux++;
			if (aux>=sizeof(crctab2)/sizeof(crctab2[0])) aux=0;
		}
		/* new checksum value */
		s=(s<<8)^crctable[i];	/* crctable->one of crctab2, crctab2b */
	}
	return s;
}

/* -------------------------------------------------------------- strncrc --- */
/* ----------------------------------------------- draft 11 crc algorithm --- */
unsigned long strncrcb(unsigned char *b,int n,unsigned long s)
{
	int	i;
	static int aux;

	while (n-- > 0) {
		/* compute the index to the crc table */
		i=(s>>24)^((unsigned int)(*b++));
    
		if (i==0) {
			/* replace an intermediate zero with the next value from the sequence */
			i=aux++;
			if (aux>=sizeof(crctab2)/sizeof(crctab2[0])) aux=0;
		}

		/* new checksum value */
		s=(s<<8)^crctable[i];	/* crctable->one of crctab2, crctab2b */
	}
	return s;
}

/* -------------------------------------------------------------- sum    --- */
/* --------------------------------------------------- old sum algorithm --- */
unsigned long sum16(unsigned char *b,int n,unsigned long s)
{
	while (n-- > 0) {
		if (s&1) s|=0x10000;
		s=((s>>1)+*b++)&0xffff;
	}
	return s;
}

unsigned long sum32(unsigned char *b,int n,unsigned long s)
{
	while (n-- > 0) {
		s+=*b++;
	}
	return s;
}

unsigned long finish_sum32(off_t unused, unsigned long s)
{
	unused=0;
	s=(s&0xffff) + (s>>16);
	return ((s&0xffff) + (s>>16)) + unused;
}

/* -------------------------------------------------------------- memcrc3 --- */
/* ----------------------------------------------- draft 12 crc algorithm --- */
/* ------------------------------------------------- 1003.2-1992 standard --- */

unsigned long memcrc3 (unsigned char *b, int n, unsigned long s)
{
	size_t i;

	for (i=n;i>0;--i) {
		s         = (s<<8) ^ crctable[  (s>>24) ^ ((unsigned int)(*b++))  ];
	}

	return s;
}

unsigned long finish_crc3 (off_t tot_len, unsigned long s)
{
	/* encode the file length as part of the crc number */
	while (tot_len!=0) {
		s         = (s<<8) ^ crctable[  (s>>24) ^ (tot_len&0xff)  ];
		tot_len >>= 8;
	}

	return ~s;
}


	
